package com.toddsoft.util;

public class ByteArrayHandler {

    private byte[] bytes;
    private int nextAddPos;
    private int nextGetPos = 0;

    public ByteArrayHandler() {
        this(16);
    }

    public ByteArrayHandler(int initialSize) {
        this.bytes = new byte[initialSize];
        this.nextAddPos = 0;
    }

    public ByteArrayHandler(byte[] ba) {
        this.bytes = ba;
        this.nextAddPos = this.bytes.length;
    }

    public byte[] getBytes() {
        if (this.bytes.length != this.nextAddPos) {
            byte[] ret = new byte[this.nextAddPos];
            System.arraycopy(this.bytes, 0, ret, 0, this.nextAddPos);
            return ret;
        } else {
            return this.bytes;
        }
    }

    public void addByte(byte b) {
        if (nextAddPos >= bytes.length) {
            byte[] temp = new byte[bytes.length * 2];
            System.arraycopy(bytes, 0, temp, 0, bytes.length);
            bytes = temp;
        }
        bytes[nextAddPos++] = b;
    }

    public byte getByte() {
        return bytes[nextGetPos++];
    }

    public void addBoolean(boolean bool) {
        addByte(bool ? (byte)1 : (byte)0);
    }

    public boolean getBoolean() {
        return (getByte() != 0);
    }

    public void addInt(int i) {

        int current = i;
    
        /* create bytes by taking 8 bits at a time */
        for (int j = 0; j < 4; j++) { //loop for 4 bytes
    
            byte b = 0;
            for (int k = 0; k < 8; k++) { //loop for 8 bits
    
                /* get the next bit from current */
                int bit = current & 1;
    
                /* shift current for next time */
                current >>>= 1;
    
                // shift b ready to add next bit
                b <<= 1;
    
                // add the bit
                b |= bit;
            }
    
            addByte(b);
        }

    }

    public int getInt() {

        int theInt = 0;

        for (int j = 3; j >= 0; j--) { //loop for 4 bytes in one int

            int byteIndex = nextGetPos + j;
            byte b = this.bytes[byteIndex];
            for (int k = 0; k < 8; k++) { //loop for 8 bits

                /* get the next bit from current */
                int bit = b & 1;

                /* shift b for next time */
                b >>>= 1;

                // shift theInt ready to add next bit
                theInt <<= 1;

                // add the bit
                theInt |= bit;
            }
        }

        nextGetPos += 4;

        return theInt;
    }

    public void addLong(long l) {

        long current = l;
    
        for (int j = 0; j < 8; j++) { //loop for 8 bytes
    
            byte b = 0;
            for (int k = 0; k < 8; k++) { //loop for 8 bits
    
                /* get the next bit from current */
                long bit = current & 1;
    
                /* shift current for next time */
                current >>>= 1;
    
                // shift b ready to add next bit
                b <<= 1;
    
                // add the bit
                b |= bit;
            }
    
            addByte(b);
        }

    }

    public long getLong() {

        long theLong = 0;

        for (int j = 7; j >= 0; j--) { //loop for 8 bytes in one long

            int byteIndex = nextGetPos + j;
            byte b = this.bytes[byteIndex];
            for (int k = 0; k < 8; k++) { //loop for 8 bits

                /* get the next bit from current */
                int bit = b & 1;

                /* shift b for next time */
                b >>>= 1;

                // shift theLong ready to add next bit
                theLong <<= 1;

                // add the bit
                theLong |= (long)bit;
            }
        }

        nextGetPos += 8;

        return theLong;
    }
}
